/// \file owl_handler.h.
///============================================================================\n
/// Name        : owl_handler.h\n
/// Author      : Gergely Lukacsy (info@dlog-reasoner.org)\n
/// Version     : 0.01\n
/// Copyright   : DERI\n
/// Description : Specialisation for Xerces DefaultHandler for OWL processing,\n
///               header file.\n
/// 
/// This file is part of the DParser and DLog 2 projects.\n
///============================================================================

#ifndef SAX_HANDLER_H_
#define SAX_HANDLER_H_

using namespace xercesc;

class OWLHANDLER;
class OWLPARSER;
class ATOMICCONCEPT;
class ATOMICROLE;
class INSTANCE;

/// Typedef for member function pointers with a given signature.
typedef void (OWLHANDLER::*HOOKFUNCTION)(PARAMETERS&);

/// Vector for storing XMLch* - member function pointer assignments.
class OWLCALLBACK {
public:
	/// Constructor that takes a Xerces String and a pointer to a member function.
	OWLCALLBACK(const XMLCh* pElement, HOOKFUNCTION pHook);

	/// Constructor that takes also a parameter vector.
	OWLCALLBACK(const XMLCh* pElement, HOOKFUNCTION pHook, PARAMETERS& params);

	/// The Xerces string to which we assign a member function.
	const XMLCh* pElementName;

	/// The member function pointer.
	HOOKFUNCTION pHookFunction;

	/// Parameters of the assignment.
	PARAMETERS mParameters;
private:
	void init(const XMLCh* pElement, HOOKFUNCTION pHook);

};

struct OWLCALLBACKSORT {
     bool operator()(OWLCALLBACK* pCallBack1, OWLCALLBACK* pCallBack2) {
    	 return (XMLString::compareString(pCallBack1->pElementName, pCallBack2->pElementName) < 0);
     }
  };

struct STRINGNCOMPARE : public std::binary_function<STRINGN&, STRINGN&, bool> {
	bool operator() (const STRINGN& s1, const STRINGN& s2) const {
		ASSERT(s1.pString != NULL);
		ASSERT(s2.pString != NULL);

		// if s1 is longer than s2 (or have equal length), then s1 < s2 iff s1 is < s2 on the length of s2
		// if s1 is strictly shorter than s2 then s1 < s2 iff s1 <= s2 on the length of s1
		if (s1.nLength >= s2.nLength) {
			return (XMLString::compareNString(s1.pString, s2.pString, s2.nLength) < 0);
		} else {
			// if s1 is strictly shorter than s2 then s1 < s2 iff s1 < s2 on the length of s1
			return (XMLString::compareNString(s1.pString, s2.pString, s1.nLength) <= 0);
		}
	}
};


/// Map for storing prefix-URI pairs
typedef MAP<STRINGN, char*, STRINGNCOMPARE> PREFIXMAP;
typedef PAIR<STRINGN, char*> STRINGNPAIR;
typedef PREFIXMAP::iterator PREFIXMAPITERATOR;

/// Class providing hooks for SAX processing ontologies in OWL2 XML presentation format.
class OWLHANDLER : public DefaultHandler {
public:
	OWLHANDLER();
	~OWLHANDLER();

	/// Xerces hook method for processing a new element.
	void startElement(
        const   XMLCh* const    uri,
        const   XMLCh* const    localname,
        const   XMLCh* const    qname,
        const   Attributes&     attrs
    );

	/// Xerces hook method for processing an end element.
    void endElement(
    		const XMLCh* const uri,
    		const XMLCh* const localname,
    		const XMLCh* const qname
    );


	/// Xerces hook method for processing content.
    virtual void characters (
        const XMLCh* const    chars,
        const XMLSize_t       length
    );

	void warning(const SAXParseException&);
    void error(const SAXParseException&);
    void fatalError(const SAXParseException&);

    /// Init function dor doing things that cannot be done at constructor time.
    void init();

    // pointer to the OWL parser
    OWLPARSER* pOWLParser;

private:
	//@{
	/// Special push function.
	template<typename T>
	void _pushAtomic(PARAMETERS& params, T*& pDummyAtomic);
	void pushAtomicConcept(PARAMETERS& params);
	void pushAtomicRole(PARAMETERS& params);
	void pushInverse(PARAMETERS& params);
	void pushInstance(PARAMETERS& params);
	void doNothing(PARAMETERS& params);
	//@}

	/// Method for extending the content of the prefix table.
	void extendPrefixTable(PARAMETERS& params);

	/// Inserts parameter pair to a paramter vector.
	void _insertParameter(PARAMETERS& parameters, PARAMPAIR pair);

	/// Simple binary search to retrieve the appropriate callback structure.
//	OWLCALLBACK* binaryHookSearch(OWLCALLBACKVECTOR& v, const XMLCh* pElement);

    /// Template function for compact representation of SAX operations.
    template<typename T>
    void pushOWLSAXElementToStack(PARAMETERS& params);

    /// Template function for compact representation of SAX operations.
    template<typename T>
    void pushOWLSAXAxiomToStack(PARAMETERS& params);

    /// Template function for compact representation of SAX operations.
    template<typename T>
    void _pushToStack(PARAMETERS& params);

    /// Template function to manipulate bPropertyCharacteristicModeOn and mPropertyCharacteristic.
    template<unsigned char F>
    void enterIntoOWLCharacteristicsMode(PARAMETERS& params);

    struct {
    	/// Boolean value for denoting the special parser state when handling property characteristics.
    	bool bPropertyCharacteristicModeOn;

    	/// Value denoting which property characteristics (functional, transitive, ...), @see ATOMICROLE::mProperties.
    	unsigned char mPropertyCharacteristic;

    	/// Boolean value for denoting the special parser state for Literal-s.
    	bool bLiteralModeOn;

    	/// Saved hok function belonging to the Literal mode.
    	OWLCALLBACK* pSavedHookStructure;
    };

	/// Callback assignment as a special (non-minimal) perfect hash table.
	OWLCALLBACK** callbacks;

	/// Number of buckets in the hash table.
	static DWORD nrBuckets;

	/// Calculates hash value for a callback structure.
	unsigned long __hash_xerces_name(const XMLCh* pName);

	/// Inserts a callback structure into the hash table.
	void register_callback(OWLCALLBACK* pCallBack);

	/// Retrieves a callback function from the hash table.
	OWLCALLBACK* obtain_callback(const XMLCh* pName);

	/// Dummy atomic concept.
	ATOMICCONCEPT* pDummyAtomicConcept;

	/// Dummy atomic role.
	ATOMICROLE* pDummyAtomicRole;

	/// Dummy instance.
	INSTANCE* pDummyInstance;

	/// Prefix table describing mappings between prefix strings an URIs
	PREFIXMAP mPrefixes;

	/// Auxiliary member to handle parameters of XML elements.
	char* pAttrCharsToRelease[2];

	/// Base prefix is stroed separately for constant access time.
	char* pBasePrefix;

	//@{
	/** Static field for fast string comparison during XML parsing. */
	static const XMLCh XMLOWLTHING[];
	static const XMLCh XMLOWLNOTHING[];
	static const XMLCh XMLOWLURI[];
	static const XMLCh XMLSubClassOf[];
	static const XMLCh XMLSubObjectPropertyOf[];
	static const XMLCh XMLSubDataPropertyOf[];
	static const XMLCh XMLDisjointClasses[];
	static const XMLCh XMLDisjointUnion[];
	static const XMLCh XMLDisjointObjectProperties[];
	static const XMLCh XMLDisjointDataProperties[];
	static const XMLCh XMLEquivalentClasses[];
	static const XMLCh XMLEquivalentObjectProperties[];
	static const XMLCh XMLEquivalentDataProperties[];
	static const XMLCh XMLObjectComplementOf[];
	static const XMLCh XMLObjectOneOf[];
	static const XMLCh XMLDataOneOf[];
	static const XMLCh XMLObjectHasSelf[];
	static const XMLCh XMLDataComplementOf[];
	static const XMLCh XMLClass[];
	static const XMLCh XMLDatatype[];
	static const XMLCh XMLObjectSomeValuesFrom[];
	static const XMLCh XMLDataSomeValuesFrom[];
	static const XMLCh XMLObjectAllValuesFrom[];
	static const XMLCh XMLDataAllValuesFrom[];
	static const XMLCh XMLObjectProperty[];
	static const XMLCh XMLDataProperty[];
	static const XMLCh XMLObjectHasValue[];
	static const XMLCh XMLDataHasValue[];
	static const XMLCh XMLInverseObjectProperty[];
	static const XMLCh XMLInverseObjectProperties[];
	static const XMLCh XMLObjectIntersectionOf[];
	static const XMLCh XMLDataIntersectionOf[];
	static const XMLCh XMLObjectUnionOf[];
	static const XMLCh XMLDataUnionOf[];
	static const XMLCh XMLClassAssertion[];
	static const XMLCh XMLNamedIndividual[];
	static const XMLCh XMLAnonymousIndividual[];
	static const XMLCh XMLObjectPropertyAssertion[];
	static const XMLCh XMLObjectPropertyDomain[];
	static const XMLCh XMLObjectPropertyRange[];
	static const XMLCh XMLDataPropertyDomain[];
	static const XMLCh XMLDataPropertyRange[];
	static const XMLCh XMLObjectMinCardinality[];
	static const XMLCh XMLObjectMaxCardinality[];
	static const XMLCh XMLObjectExactCardinality[];
	static const XMLCh XMLDataMinCardinality[];
	static const XMLCh XMLDataMaxCardinality[];
	static const XMLCh XMLDataExactCardinality[];

	static const XMLCh XMLIRI[];
	static const XMLCh XMLFunctionalObjectProperty[];
	static const XMLCh XMLFunctionalDataProperty[];
	static const XMLCh XMLInverseFunctionalObjectProperty[];
	static const XMLCh XMLReflexiveObjectProperty[];
	static const XMLCh XMLIrreflexiveObjectProperty[];
	static const XMLCh XMLSymmetricObjectProperty[];
	static const XMLCh XMLAsymmetricObjectProperty[];
	static const XMLCh XMLTransitiveObjectProperty[];

	static const XMLCh XMLSameIndividual[];
	static const XMLCh XMLDifferentIndividuals[];
	static const XMLCh XMLNegativeObjectPropertyAssertion[];
	static const XMLCh XMLDataPropertyAssertion[];
	static const XMLCh XMLNegativeDataPropertyAssertion[];

	static const XMLCh XMLHasKey[];
	static const XMLCh XMLPropertyChain[];

	static const XMLCh XMLLiteral[];
	static const XMLCh XMLPrefix[];

	static const XMLCh XMLName[];
	static const XMLCh XMLAbbreviatedIRI[];
	static const XMLCh XMLCardinality[];
	static const XMLCh XMLOntology[];
	static const XMLCh XMLBase[];

	static const XMLCh XMLDatatypeDefinition[];
	static const XMLCh XMLDatatypeRestriction[];
	static const XMLCh XMLFacet[];
	static const XMLCh XMLFacetRestriction[];

	static const XMLCh XMLDataTypeIRI[];
	static const XMLCh XMLImport[];
	static const XMLCh XMLDeclaration[];
	//@}

};


#endif /* SAX_HANDLER_H_ */
